Skip to content

feat: update accounts:set to work with keychain managers#3696

Open
k80bowman wants to merge 4 commits into
feat/credential-mgr-integrationfrom
k80/accounts-set
Open

feat: update accounts:set to work with keychain managers#3696
k80bowman wants to merge 4 commits into
feat/credential-mgr-integrationfrom
k80/accounts-set

Conversation

@k80bowman
Copy link
Copy Markdown
Contributor

@k80bowman k80bowman commented May 8, 2026

Summary

Updates the accounts:set command to work with keychain managers.

Type of Change

Breaking Changes (major semver update)

  • Add a ! after your change type to denote a change that breaks current behavior

Feature Additions (minor semver update)

  • feat: Introduces a new feature to the codebase

Patch Updates (patch semver update)

  • fix: Bug fix
  • deps: Dependency upgrade
  • revert: Revert a previous commit
  • chore: Change that does not affect production code
  • refactor: Refactoring existing code without changing behavior
  • test: Add/update/remove tests

Testing

Notes:

  1. Check out this branch and run npm i && npm run build
  2. Run ./bin/run login to log in to your first account.
  3. Run heroku accounts:add account1 to add this account to your accounts cache for .netrc
  4. Logout of this account in the browser and then log in to a second account
  5. Run ./bin/run login to log in to your second account
  6. Run heroku accounts:add account2 to add this second account to your accounts cache for .netrc

Steps:

  1. Run ./bin/run accounts:set <username for account 1>
  2. Run ./bin/run apps and you should see the apps for account 1
  3. Run ./bin/run accounts:set <username for account 2>
  4. Run ./bin/run apps and you should see the apps for account 2
  5. Run HEROKU_NETRC_WRITE=true ./bin/run accounts:set account1
  6. Run HEROKU_NETRC_WRITE=true ./bin/run apps and you should see the apps for account 1
  7. Run HEROKU_NETRC_WRITE=true ./bin/run accounts:set account2
  8. Run HEROKU_NETRC_WRITE=true ./bin/run apps and you should see the apps for account 2

Screenshots (if applicable)

Related Issues

GUS work item: W-20867209

@k80bowman k80bowman requested a review from a team as a code owner May 8, 2026 16:25
@k80bowman k80bowman temporarily deployed to AcceptanceTests May 8, 2026 16:25 — with GitHub Actions Inactive
@k80bowman k80bowman temporarily deployed to AcceptanceTests May 8, 2026 16:25 — with GitHub Actions Inactive
@k80bowman k80bowman temporarily deployed to AcceptanceTests May 8, 2026 16:25 — with GitHub Actions Inactive
@k80bowman k80bowman temporarily deployed to AcceptanceTests May 8, 2026 16:25 — with GitHub Actions Inactive
@k80bowman k80bowman temporarily deployed to AcceptanceTests May 8, 2026 17:57 — with GitHub Actions Inactive
@k80bowman k80bowman temporarily deployed to AcceptanceTests May 8, 2026 17:57 — with GitHub Actions Inactive
@k80bowman k80bowman temporarily deployed to AcceptanceTests May 8, 2026 17:57 — with GitHub Actions Inactive
@k80bowman k80bowman temporarily deployed to AcceptanceTests May 8, 2026 17:57 — with GitHub Actions Inactive
@k80bowman k80bowman temporarily deployed to AcceptanceTests May 8, 2026 21:04 — with GitHub Actions Inactive
@k80bowman k80bowman temporarily deployed to AcceptanceTests May 8, 2026 21:04 — with GitHub Actions Inactive
@k80bowman k80bowman temporarily deployed to AcceptanceTests May 8, 2026 21:04 — with GitHub Actions Inactive
@k80bowman k80bowman temporarily deployed to AcceptanceTests May 8, 2026 21:04 — with GitHub Actions Inactive
@k80bowman k80bowman temporarily deployed to AcceptanceTests May 11, 2026 13:57 — with GitHub Actions Inactive
@k80bowman k80bowman temporarily deployed to AcceptanceTests May 11, 2026 13:57 — with GitHub Actions Inactive
@k80bowman k80bowman temporarily deployed to AcceptanceTests May 11, 2026 13:57 — with GitHub Actions Inactive
@k80bowman k80bowman temporarily deployed to AcceptanceTests May 11, 2026 13:57 — with GitHub Actions Inactive
Copy link
Copy Markdown
Contributor

@michaelmalave michaelmalave left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving some comments. Nothing blocking & implementation looks good overall!

}

AccountsModule.set(name)
await AccountsModule.set(name, this.config.dataDir)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The match checks both name and username, but the raw input is passed to set() where the netrc path does a file lookup by that string. Should we resolve the matched account to ensure the correct identifier reaches each storage path?

it('returns an error if the account is not in the list', async function () {
listStub.resolves([{name: 'test-account', username: 'user1'}, {name: 'test-account-2', username: 'user2'}])
await runCommand(Cmd, ['test-account-3'])
.catch((error: Error) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not major but the .catch() pattern validates the error message but doesn't fail if no error occurs. Should we adopt the try/catch + expect.fail() pattern used in newer tests like rake and data/pg to ensure the error path is actually exercised?

const accounts = await AccountsModule.list()
const accountExists = accounts.some(account => account.name === name || account.username === name)

if (!(accountExists)) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So small but probably dont need double parens here. Might be simplified for clarity.

remove(name: string): void
set(name: string): Promise<void>
set(name: string, dataDir: string): Promise<void>
writeLoginState(configDir: string, name: string): Promise<void>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like something IAccountsWrapper wouldn't need to implement. Should we keep it off the interface and stub it a different way in tests?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants